package com.fivefu.core.hik.services.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fivefu.base.common.utils.str.StrUtils;
import com.fivefu.core.hik.constant.HikRequestTypeEnum;
import com.fivefu.core.hik.dto.request.PageReq;
import com.fivefu.core.hik.dto.response.*;
import com.fivefu.core.hik.entity.DbHikCamera;
import com.fivefu.core.hik.services.*;
import com.fivefu.core.hik.vo.CameraTimeRangeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CameraServiceImpl implements CameraService {

    @Autowired
    private HikvisionService hikvisionService;
    @Autowired
    private DbHikCameraService dbHikCameraService;
    @Autowired
    private DbHikRegionsService dbHikRegionsService;
    @Autowired
    private DbHikRegionsCameraService dbHikRegionsCameraService;

    /**
     * 获取监控点列表数据
     */
    @Override
    public void getCameraList(Integer version){
        Integer pageNo = 1;
        Integer pageSize = 1000;
        List<String> cameraIndexCodes = new ArrayList<>();
        if (version.equals(1)){
            getCameraListV1(pageNo, pageSize,cameraIndexCodes);
        }else{
            getCameraListV2(pageNo, pageSize,cameraIndexCodes);
        }
        dbHikCameraService.deleteHikCamera(cameraIndexCodes,"sys");
    }

    /**
     * 分页获取监控点列表数据_v1
     * @param pageNo 当前页码
     * @param pageSize 分页大小
     * @param cameraIndexCodes
     */
    public void getCameraListV1(Integer pageNo, Integer pageSize, List<String> cameraIndexCodes){
        //分页查询参数
        PageReq pageReq = new PageReq(pageNo,pageSize);
        String body = JSON.toJSONString(pageReq);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.CAMERALISTV1;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (result != null && "0".equals(result.getCode())){//调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)){
                ResponsePage resultPage = JSON.parseObject(resultData, ResponsePage.class);

                resultPage.getList().forEach(obj -> {
                    HikCameraPageV1Resp resp = JSON.parseObject(JSON.toJSONString(obj),HikCameraPageV1Resp.class);
                    DbHikCamera camera = resp.replaceDbHikCamera();
                    //编辑监控点信息
                    dbHikCameraService.editHikCamera(camera);
                    cameraIndexCodes.add(camera.getCameraIndexCode());
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)){
                    getCameraListV1( pageNo + 1, pageSize, cameraIndexCodes);
                }
            }
        }
    }

    /**
     * 分页获取监控点列表数据_v2
     * @param pageNo 当前页码
     * @param pageSize 分页大小
     * @param cameraIndexCodes
     */
    public void getCameraListV2(Integer pageNo, Integer pageSize, List<String> cameraIndexCodes){
        //分页查询参数
        PageReq pageReq = new PageReq(pageNo,pageSize);
        String body = JSON.toJSONString(pageReq);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.CAMERALISTV2;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (result != null && "0".equals(result.getCode())){//调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)){
                ResponsePage resultPage = JSON.parseObject(resultData, ResponsePage.class);

                resultPage.getList().forEach(obj -> {
                    HikCameraPageV2Resp resp = JSON.parseObject(JSON.toJSONString(obj), HikCameraPageV2Resp.class);
                    DbHikCamera camera = resp.replaceDbHikCamera();
                    //编辑监控点信息
                    dbHikCameraService.editHikCamera(camera);
                    cameraIndexCodes.add(camera.getCameraIndexCode());
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)){
                    getCameraListV2( pageNo + 1, pageSize, cameraIndexCodes);
                }
            }
        }
    }

    /**
     * 查询监控点详情
     * @param cameraIndexCode 监控点编号
     */
    public void getCameraDetail(String cameraIndexCode){
        JSONObject obj = new JSONObject();
        obj.put("cameraIndexCode",cameraIndexCode);
        //分页查询参数
        String body = JSON.toJSONString(obj);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.CAMERADETAIL;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (result != null && "0".equals(result.getCode())){//调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)){
                HikCameraPageV1Resp resp = JSON.parseObject(resultData,HikCameraPageV1Resp.class);
                DbHikCamera camera = resp.replaceDbHikCamera();
                //编辑监控点信息
                dbHikCameraService.editHikCamera(camera);
            }
        }
    }

    /**
     * 查询区域下级监控点列表
     */
    @Override
    public void queryCameraByRegionIndexCode(){
        Integer pageNo = 1;
        Integer pageSize = 1000;
        //查询未删除区域唯一标识集合
        List<String> regionIDs = dbHikRegionsService.queryRegionIDs();
        Map<String, Map<String, Long>> regionMap = dbHikRegionsCameraService.queryRegionsCameraRegionMap();

        //循环查询区域监控点关联关系
        for (String regionIndexCode : regionIDs) {
            //获取下级所有监控点唯一标识集合
            List<String> cameraList = queryCameraByRegionIndexCode(pageNo, pageSize, regionIndexCode);

            if (regionMap.containsKey(regionIndexCode)){
                Map<String, Long> cameraIndexMap = regionMap.get(regionIndexCode);
                Set<String> cameraIndexSet = cameraIndexMap.keySet();

                //已添加监控点关联信息
                List<String> hasList = cameraIndexSet.stream().filter(k -> cameraList.contains(k)).collect(Collectors.toList());
                //去掉已存在的监控点
                cameraList.removeAll(hasList);

                List<Long> regionCameraIDs = new ArrayList<>();
                cameraIndexSet.removeAll(hasList);
                //删除多余监控点
                for (String cameraIndexCode : cameraIndexSet) {
                    Long regionCameraID = cameraIndexMap.get(cameraIndexCode);
                    regionCameraIDs.add(regionCameraID);
                }
                if (!regionCameraIDs.isEmpty()) {
                    dbHikRegionsCameraService.deleteRegionCameras(regionIndexCode, regionCameraIDs);
                }
            }
            //新增探头关联
            if (!cameraList.isEmpty()){
                dbHikRegionsCameraService.insertRegionCameras(regionIndexCode, cameraList);
            }
        }
        //删除其他区域关联关系
        dbHikRegionsCameraService.deleteNotContainRegionsCameraByRegionIndexCodes(regionIDs);
    }

    @Override
    public void queryCameraDetail(String cameraIndexCode) {
        getCameraDetail(cameraIndexCode);
    }

    /**
     * 增量获取监控点数据
     * @param stime     更新开始时间（例：2019-08-06T14:01:17.839+0800）
     * @param etime     更新结束时间（例：2019-08-06T14:01:17.839+0800）
     * @param page
     * @param limit
     */
    @Override
    public void queryCameraData(String stime,String etime,Integer page,Integer limit) {
        queryCameraByTime(page,limit,stime,etime);
    }

    /**
     * 查询区域下级监控点列表
     * @param pageNo 当前页码
     * @param pageSize    分页大小
     * @param regionIndexCode 区域编号唯一标识
     */
    public List<String> queryCameraByRegionIndexCode(Integer pageNo, Integer pageSize, String regionIndexCode){
        List<String> cameraList = new ArrayList<>();
        JSONObject param = new JSONObject();
        param.put("pageNo",pageNo);
        param.put("pageSize",pageSize);
        param.put("regionIndexCode",regionIndexCode);
        //分页查询参数
        String body = JSON.toJSONString(param);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.CAMERAREGION;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (result != null && "0".equals(result.getCode())){//调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)){
                ResponsePage resultPage = JSON.parseObject(resultData, ResponsePage.class);

                resultPage.getList().forEach(obj -> {
                    HikCameraPageV1Resp resp = JSON.parseObject(JSON.toJSONString(obj),HikCameraPageV1Resp.class);
                    cameraList.add(resp.getCameraIndexCode());
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)){
                    List<String> childList = queryCameraByRegionIndexCode(pageNo + 1, pageSize, regionIndexCode);

                    cameraList.addAll(childList);
                }
            }
        }
        return cameraList;
    }

    /**
     * 增量获取监控点信息
     * @param pageNo 当前页码
     * @param pageSize 分页大小
     * @param startTime 针对更新时间的查询开始日期，IOS8601格式，参考附录B ISO8601时间格式说明
     * @param endTime 针对更新时间的查询截止日期，IOS8601格式，参考附录B ISO8601时间格式说明
     */
    public void queryCameraByTime(Integer pageNo, Integer pageSize, String startTime, String endTime){
        JSONObject obj = new JSONObject();
        obj.put("pageNo",pageNo);
        obj.put("pageSize",pageSize);
        obj.put("startTime",startTime);
        obj.put("endTime",endTime);
        //分页查询参数
        String body = JSON.toJSONString(obj);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.CAMERAINCREMENT;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (result != null && "0".equals(result.getCode())){//调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)){
                ResponsePage resultPage = JSON.parseObject(resultData,ResponsePage.class);
                resultPage.getList().forEach(vo -> {
                    CameraTimeRangeVo cameraVo = JSON.parseObject(JSON.toJSONString(vo), CameraTimeRangeVo.class);
                    DbHikCamera camera = cameraVo.replaceDbHikCamera();
                    //编辑监控点数据
                    dbHikCameraService.editHikCamera(camera);
                });
            }
        }
    }

    /**
     * 分页获取监控点列表数据_v1  汇总用的
     * @param pageNo 当前页码
     * @param pageSize 分页大小
     */
    @Override
    public List<DbHikCamera> getCameraListCollect(Integer pageNo,Integer pageSize) {
        List<DbHikCamera> resultList = new ArrayList<>();
        //分页查询参数
        PageReq pageReq = new PageReq(pageNo,pageSize);
        String body = JSON.toJSONString(pageReq);

        //查询类型枚举
        HikRequestTypeEnum typeEnum = HikRequestTypeEnum.CAMERALISTV1;

        //调用接口
        ResponseResult result = hikvisionService.doPostString(typeEnum.getUrl(), body, null, null, typeEnum.getType());
        if (result != null && "0".equals(result.getCode())){//调用成功
            String resultData = result.getData().toString();
            if (StrUtils.isNotNull(resultData)){
                ResponsePage resultPage = JSON.parseObject(resultData, ResponsePage.class);

                resultPage.getList().forEach(obj -> {
                    HikCameraPageV1Resp resp = JSON.parseObject(JSON.toJSONString(obj),HikCameraPageV1Resp.class);
                    DbHikCamera camera = resp.replaceDbHikCamera();
                    resultList.add(camera);
                });

                //循环查询分页数据
                if (resultPage.getTotal() > ((pageNo - 1) * pageSize + pageSize)){
                    List<DbHikCamera> cameraListCollect = getCameraListCollect(pageNo + 1, pageSize);
                    resultList.addAll(cameraListCollect);
                }
            }
        }
        return resultList;
    }

    /**
     * 根据监控点编号查询监控点详情
     */
    @Override
    public void getAllCameraDetail() {
        //查询监控点表所有数据信息
        List<DbHikCamera> cameraList = dbHikCameraService.queryAllCamera();
        if (null != cameraList && cameraList.size() >0) {
            cameraList.forEach(camera -> getCameraDetail(camera.getCameraIndexCode()));
        }
    }
}
